/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package treegenerator.gui;

import treegenerator.arbaro.LeafTextureCreator;
import treegenerator.arbaro.StemTextureCreator;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.PixelGrabber;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

/**
 *
 * @author jannes
 */
public class TexturePanel extends JPanel{    
    private Box trunkTextureBox, stemTextureBox, leafTextureBox; 
    private Box trunkTextures,stemTextures,leafTextures;
    private JTextField txtSeedLeaf;
    private JTextField txtHorizontalTrunk,txtVerticalTrunk,txtTopTrunk,txtSeedTrunk;
    private JTextField txtHorizontalStem,txtVerticalStem,txtTopStem,txtSeedStem;        
    private StemTextureCreator stemTextureCreator, trunkTextureCreator;      
    private LeafTextureCreator leafTextureCreator;
    private Thumbnail trunkTexture,stemTexture,leafTexture;    
    
    JFileChooser jfc;
    public TexturePanel(){        
        trunkTextureCreator = new StemTextureCreator();
        stemTextureCreator = new StemTextureCreator();                   
        leafTextureCreator = new LeafTextureCreator();
        this.setLayout(new BorderLayout());                               
        trunkTexture = new Thumbnail(null,0,0);        
        stemTexture = new Thumbnail(null,0,0);        
        leafTexture = new Thumbnail(null,0,0);    
        this.setPreferredSize(new Dimension(250,100));
        this.setMaximumSize(new Dimension(250,10000));
                        
        JLabel lblTitle = new JLabel("Texture Parameters");
        lblTitle.setFont(new Font(lblTitle.getFont().getName(), Font.BOLD, 20));
        Box hb = Box.createHorizontalBox();        
        hb.add(Box.createHorizontalGlue());
        hb.add(lblTitle);
        hb.add(Box.createHorizontalGlue());
        add(hb,BorderLayout.NORTH);
        
        Box b = Box.createVerticalBox();        
        this.add(new JScrollPane(b),BorderLayout.CENTER);        
        b.setOpaque(true);
        b.setBackground(Color.WHITE);
        b.setBorder(BorderFactory.createLineBorder(Color.GRAY));
        trunkTextureBox = Box.createVerticalBox();
        stemTextureBox = Box.createVerticalBox();
        leafTextureBox = Box.createVerticalBox();                
        b.add(trunkTextureBox);        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        JLabel label = new JLabel("___________________");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 20));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        b.add(hb);                        
        b.add(stemTextureBox);        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("___________________");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 20));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        b.add(hb);                    
        b.add(leafTextureBox);          
                
        jfc = new JFileChooser();                
        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Trunk");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 20));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        trunkTextureBox.add(hb);        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Preview");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        trunkTextureBox.add(hb);        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        hb.add(trunkTexture);
        hb.add(Box.createHorizontalGlue());
        trunkTextureBox.add(hb);   
        trunkTextureBox.add(new JSeparator(JSeparator.HORIZONTAL));                      
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Parameters:");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        trunkTextureBox.add(hb);                
        hb = Box.createHorizontalBox();    
        hb.add(new JLabel("seed:"));
        txtSeedTrunk = new JTextField("13");
        txtSeedTrunk.setMaximumSize(new Dimension(50,25));
        txtSeedTrunk.setPreferredSize(new Dimension(50,25));        
        txtSeedTrunk.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void changedUpdate(DocumentEvent e) {
                updateTrunkSeed();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateTrunkSeed();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateTrunkSeed();
            }
        });
        hb.add(Box.createHorizontalGlue());
        hb.add(txtSeedTrunk);
        trunkTextureBox.add(hb);
        hb = Box.createHorizontalBox();        
        hb.add(new JLabel("#horizontal:"));
        txtHorizontalTrunk = new JTextField("4");
        txtHorizontalTrunk.setMaximumSize(new Dimension(50,25));
        txtHorizontalTrunk.setPreferredSize(new Dimension(50,25));
        txtHorizontalTrunk.getDocument().addDocumentListener(new DocumentListener() {
            
            private void updateTileCount(){
                try{
                    if(Integer.parseInt(txtHorizontalTrunk.getText()) != trunkTextureCreator.getTiles_x()){
                        updateTrunkTexture();
                    }
                }catch(Exception exc){}
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {                
                updateTileCount();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateTileCount();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateTileCount();
            }
        });
        hb.add(Box.createHorizontalGlue());
        hb.add(txtHorizontalTrunk);
        trunkTextureBox.add(hb);
        hb = Box.createHorizontalBox();        
        hb.add(new JLabel("#vertical:"));
        txtVerticalTrunk = new JTextField("4");
        txtVerticalTrunk.setMaximumSize(new Dimension(50,25));
        txtVerticalTrunk.setPreferredSize(new Dimension(50,25));
        txtVerticalTrunk.getDocument().addDocumentListener(new DocumentListener() {            
            private void updateTileCount(){
                try{
                    if(Integer.parseInt(txtVerticalTrunk.getText()) != trunkTextureCreator.getTiles_y()){
                        updateTrunkTexture();
                    }
                }catch(Exception exc){}
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {                
                updateTileCount();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateTileCount();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateTileCount();
            }
        });
        hb.add(Box.createHorizontalGlue());
        hb.add(txtVerticalTrunk);
        trunkTextureBox.add(hb);
        hb = Box.createHorizontalBox();        
        hb.add(new JLabel("#top:"));
        txtTopTrunk = new JTextField("2");
        txtTopTrunk.setMaximumSize(new Dimension(50,25));
        txtTopTrunk.setPreferredSize(new Dimension(50,25));
        txtTopTrunk.getDocument().addDocumentListener(new DocumentListener() {
            
            private void updateTileCount(){
                try{
                    if(Integer.parseInt(txtTopTrunk.getText()) != trunkTextureCreator.getTiles_top()){
                        updateTrunkTexture();
                    }
                }catch(Exception exc){}
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {                
                updateTileCount();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateTileCount();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateTileCount();
            }
        });
        hb.add(Box.createHorizontalGlue());
        hb.add(txtTopTrunk);
        trunkTextureBox.add(hb);
        trunkTextureBox.add(new JSeparator(JSeparator.HORIZONTAL));                      
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Tiles");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        trunkTextureBox.add(hb);                
        JButton btnAddTrunkTile = new JButton("+");
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        hb.add(btnAddTrunkTile);
        hb.add(Box.createHorizontalGlue());
        trunkTextureBox.add(hb);
        btnAddTrunkTile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                int result = jfc.showOpenDialog(null);                
                if(result == JFileChooser.APPROVE_OPTION){
                    addTrunkTile(jfc.getSelectedFile());
                }
            }
        });        
        trunkTextures = Box.createVerticalBox();
        trunkTextureBox.add(trunkTextures);
        
        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Stem");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 20));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        stemTextureBox.add(hb);
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Preview");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        stemTextureBox.add(hb);        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        hb.add(stemTexture);
        hb.add(Box.createHorizontalGlue());
        stemTextureBox.add(hb);        
        stemTextureBox.add(new JSeparator(JSeparator.HORIZONTAL));                      
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Parameters:");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        stemTextureBox.add(hb);        
        hb = Box.createHorizontalBox();    
        hb.add(new JLabel("seed:"));
        txtSeedStem = new JTextField("13");
        txtSeedStem.setMaximumSize(new Dimension(50,25));
        txtSeedStem.setPreferredSize(new Dimension(50,25)); 
        txtSeedStem.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void changedUpdate(DocumentEvent e) {
                updateStemSeed();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateStemSeed();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateStemSeed();
            }
        });
        hb.add(Box.createHorizontalGlue());
        hb.add(txtSeedStem);
        stemTextureBox.add(hb);
        hb = Box.createHorizontalBox();        
        hb.add(new JLabel("#horizontal:"));
        txtHorizontalStem = new JTextField("4");
        txtHorizontalStem.setMaximumSize(new Dimension(50,25));
        txtHorizontalStem.setPreferredSize(new Dimension(50,25));
        txtHorizontalStem.getDocument().addDocumentListener(new DocumentListener() {
            
            private void updateTileCount(){
                try{
                    if(Integer.parseInt(txtHorizontalStem.getText()) != stemTextureCreator.getTiles_x()){
                        updateStemTexture();
                    }
                }catch(Exception exc){}
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {                
                updateTileCount();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateTileCount();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateTileCount();
            }
        });
        hb.add(Box.createHorizontalGlue());
        hb.add(txtHorizontalStem);
        stemTextureBox.add(hb);
        hb = Box.createHorizontalBox();        
        hb.add(new JLabel("#vertical:"));
        txtVerticalStem = new JTextField("4");
        txtVerticalStem.setMaximumSize(new Dimension(50,25));
        txtVerticalStem.setPreferredSize(new Dimension(50,25));
        txtVerticalStem.getDocument().addDocumentListener(new DocumentListener() {
            
            private void updateTileCount(){
                try{
                    if(Integer.parseInt(txtVerticalStem.getText()) != stemTextureCreator.getTiles_y()){
                        updateStemTexture();
                    }
                }catch(Exception exc){}
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {                
                updateTileCount();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateTileCount();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateTileCount();
            }
        });

        hb.add(Box.createHorizontalGlue());
        hb.add(txtVerticalStem);
        stemTextureBox.add(hb);
        hb = Box.createHorizontalBox();        
        hb.add(new JLabel("#top:"));
        txtTopStem = new JTextField("2");
        txtTopStem.setMaximumSize(new Dimension(50,25));
        txtTopStem.setPreferredSize(new Dimension(50,25));
        txtTopStem.getDocument().addDocumentListener(new DocumentListener() {
            
            private void updateTileCount(){
                try{
                    if(Integer.parseInt(txtTopStem.getText()) != stemTextureCreator.getTiles_top()){
                        updateStemTexture();
                    }
                }catch(Exception exc){}
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {                
                updateTileCount();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateTileCount();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateTileCount();
            }
        });

        hb.add(Box.createHorizontalGlue());
        hb.add(txtTopStem);
        stemTextureBox.add(hb);
        stemTextureBox.add(new JSeparator(JSeparator.HORIZONTAL));                      
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Tiles");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        stemTextureBox.add(hb);     
        JButton btnAddStemTile = new JButton("+");
        stemTextureBox.add(btnAddStemTile);
        btnAddStemTile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                int result = jfc.showOpenDialog(null);                
                if(result == JFileChooser.APPROVE_OPTION){
                    addStemTile(jfc.getSelectedFile());
                }
            }
        });                
        stemTextures = Box.createVerticalBox();
        stemTextureBox.add(stemTextures);
        
        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Leaf");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 20));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        leafTextureBox.add(hb);
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Preview");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        leafTextureBox.add(hb);        
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        hb.add(leafTexture);
        hb.add(Box.createHorizontalGlue());
        leafTextureBox.add(hb);        
        leafTextureBox.add(new JSeparator(JSeparator.HORIZONTAL));                      
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Parameters:");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        leafTextureBox.add(hb);        
        hb = Box.createHorizontalBox();    
        hb.add(new JLabel("seed:"));        
        txtSeedLeaf = new JTextField("0");
        txtSeedLeaf.setMaximumSize(new Dimension(50,25));
        txtSeedLeaf.setPreferredSize(new Dimension(50,25));        
        txtSeedLeaf.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void changedUpdate(DocumentEvent e) {
                updateLeafSeed();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                updateLeafSeed();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                updateLeafSeed();
            }
        });
        hb.add(Box.createHorizontalGlue());
        hb.add(txtSeedLeaf);
        leafTextureBox.add(hb);
        leafTextureBox.add(new JSeparator(JSeparator.HORIZONTAL));                      
        hb = Box.createHorizontalBox();
        hb.add(Box.createHorizontalGlue());
        label = new JLabel("Tiles");
        label.setFont(new Font(label.getFont().getName(), Font.BOLD, 15));
        hb.add(label);
        hb.add(Box.createHorizontalGlue());
        leafTextureBox.add(hb);     
        JButton btnAddLeafTile = new JButton("+");
        leafTextureBox.add(btnAddLeafTile);
        btnAddLeafTile.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                int result = jfc.showOpenDialog(null);                
                if(result == JFileChooser.APPROVE_OPTION){                                        
                    addLeafTile(jfc.getSelectedFile());
                }
            }
        });
        leafTextures = Box.createVerticalBox();
        leafTextureBox.add(leafTextures);
    }                
    
    public void updateTrunkTexture(){
        try{
            trunkTextureCreator.setTiles_top(Integer.parseInt(txtTopTrunk.getText()));
            int x = Integer.parseInt(txtHorizontalTrunk.getText());
            int y = Integer.parseInt(txtVerticalTrunk.getText());
            trunkTextureCreator.setTiles_x(x);
            trunkTextureCreator.setTiles_y(y);            
            Image stemImage = trunkTextureCreator.createImage(Long.parseLong(txtSeedTrunk.getText()));
            trunkTexture.setIconImage(stemImage,32*x,32*y);                 
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    
    public void updateStemTexture(){
        try{
            stemTextureCreator.setTiles_top(Integer.parseInt(txtTopStem.getText()));
            int x = Integer.parseInt(txtHorizontalStem.getText());
            int y = Integer.parseInt(txtVerticalStem.getText());
            stemTextureCreator.setTiles_x(x);
            stemTextureCreator.setTiles_y(y);            
            Image stemImage = stemTextureCreator.createImage(Long.parseLong(txtSeedStem.getText()));
            stemTexture.setIconImage(stemImage,32*x,32*y);                 
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    
    public void updateLeafTexture(){
        Image leafImage = leafTextureCreator.createImage();
        int sideCount = leafTextureCreator.sideCount();
        leafTexture.setIconImage(leafImage, 32*sideCount, 32*sideCount);
    }        
    
    public Material getTrunkMaterial(AssetManager assetManager){
        return trunkTextureCreator.createMaterial(stemTexture.getOriginalImage(), assetManager);
    }
    
    public Material getStemMaterial(AssetManager assetManager){
        return stemTextureCreator.createMaterial(stemTexture.getOriginalImage(), assetManager);
    }
    
    public Material getLeafMaterial(AssetManager assetManager){
        return leafTextureCreator.createMaterial(leafTexture.getOriginalImage(), assetManager);
    }
    
    public int getLeafSides(){
        return leafTextureCreator.sideCount();
    }
    
    public void setTrunkSeed(String seed){
        txtSeedTrunk.setText(seed);
    }       
    
    public void setStemSeed(String seed){
        txtSeedStem.setText(seed);
    }
    
    public void setLeafSeed(String seed){
        txtSeedLeaf.setText(seed);
    }
    
    public long getLeafSeed(){
        try{
            return Long.parseLong(txtSeedLeaf.getText());
        }catch(Exception exc){
            return 13l;
        }
    }
    
    public void setTrunkHorizontal(String count){
        txtHorizontalTrunk.setText(count);
    }
    
    public void setStemHorizontal(String count){
        txtHorizontalStem.setText(count);
    }
    
    public void setTrunkVertical(String count){
        txtVerticalTrunk.setText(count);
    }
    
    public void setStemVertical(String count){
        txtVerticalStem.setText(count);
    }
    
    public void setTrunkTop(String count){
        txtTopTrunk.setText(count);
    }
    
    public void setStemTop(String count){
        txtTopStem.setText(count);
    }
    
    public void addTrunkTile(File file){
        final Thumbnail thumbnail = new Thumbnail(file);                                        
        trunkTextureCreator.addTile(thumbnail.getOriginalImage());
        updateTrunkTexture();
        final Box hb = Box.createHorizontalBox();
        hb.add(thumbnail);
        JButton removeTile = new JButton("X");
        hb.add(removeTile);
        removeTile.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                trunkTextureCreator.removeTile(thumbnail.getOriginalImage());
                trunkTextureBox.remove(hb);
                trunkTextureBox.revalidate();
                updateTrunkTexture();
            }
        });
        trunkTextures.add(hb);                         
        trunkTextureBox.revalidate();        
    }
    
    public void addStemTile(File file){
        final Thumbnail thumbnail = new Thumbnail(file);                                        
        stemTextureCreator.addTile(thumbnail.getOriginalImage());
        updateStemTexture();
        final Box hb = Box.createHorizontalBox();
        hb.add(thumbnail);
        JButton removeTile = new JButton("X");
        hb.add(removeTile);
        removeTile.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                stemTextureCreator.removeTile(thumbnail.getOriginalImage());
                stemTextureBox.remove(hb);
                stemTextureBox.revalidate();
                updateStemTexture();
            }
        });
        stemTextures.add(hb);                         
        stemTextureBox.revalidate();
    }
    
    public void addLeafTile(File file){
        final Thumbnail thumbnail = new Thumbnail(file); 
        leafTextureCreator.addTile(thumbnail.getOriginalImage());
        updateLeafTexture();
        final Box hb = Box.createHorizontalBox();
        hb.add(thumbnail);
        JButton removeTile = new JButton("X");
        hb.add(removeTile);
        removeTile.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                leafTextureCreator.removeTile(thumbnail.getOriginalImage());
                leafTextureBox.remove(hb);
                leafTextureBox.revalidate();
                updateLeafTexture();
            }
        });
        leafTextures.add(hb);
        leafTextureBox.revalidate();
    }
    
    public void reset(){        
        trunkTextures.removeAll();
        stemTextures.removeAll();
        leafTextures.removeAll();
        trunkTextureCreator.removeAllTiles();
        stemTextureCreator.removeAllTiles();
        leafTextureCreator.removeAllTiles();
    }
    
    public void resetSeeds(){
        txtSeedTrunk.setText("13");
        txtSeedStem.setText("13");
        txtSeedLeaf.setText("0");
    }
    
    public HashMap<String,String> saveCurrentTextures(File projectDir, String treeType){                
        HashMap<String,String> result = new HashMap<String, String>();       
        File baseDir = new File(projectDir, "assets/Textures/Trees/" + treeType);        
        File fTrunk = new File(baseDir,"Trunk");
        String trunkName = "/" + trunkTextureCreator.getSeed() + ".png";
        fTrunk = new File(fTrunk, trunkName); 
        File fStem = new File(baseDir,"Stem");
        String stemName = "/" + stemTextureCreator.getSeed() + ".png";
        fStem = new File(fStem, stemName); 
        File fLeaves = new File(baseDir,"Leaf");
        String leafName = "/" + leafTextureCreator.getSeed() + ".png";
        fLeaves = new File(fLeaves, leafName);         
        try {                        
            fTrunk.getParentFile().mkdirs();
            ImageIO.write((BufferedImage)stemTexture.getOriginalImage(), "png", fTrunk);            
            fStem.getParentFile().mkdirs();
            ImageIO.write((BufferedImage)stemTexture.getOriginalImage(), "png", fStem);            
            fLeaves.getParentFile().mkdirs();
            ImageIO.write((BufferedImage)leafTexture.getOriginalImage(), "png", fLeaves);            
            result.put("TrunkTexture",trunkName);
            result.put("StemTexture",stemName);
            result.put("LeafTexture",leafName);
        } catch (Exception ex) {            
            JOptionPane.showMessageDialog(null, ex);
        }        
        return result;
    }
    
    public void writeTextureParams(BufferedWriter bw) throws IOException{        
        bw.write("\t<trunkTextures>");                        
        bw.newLine();                        
        bw.write("\t\t<horizontalTiles>" + txtHorizontalTrunk.getText() + "</horizontalTiles>");                        
        bw.newLine();
        bw.write("\t\t<verticalTiles>" + txtVerticalTrunk.getText() + "</verticalTiles>");                        
        bw.newLine();
        bw.write("\t\t<topTiles>" + txtTopTrunk.getText() + "</topTiles>");                        
        bw.newLine();
        bw.write("\t</trunkTextures>");   
        bw.write("\t<stemTextures>");                        
        bw.newLine();                        
        bw.write("\t\t<horizontalTiles>" + txtHorizontalStem.getText() + "</horizontalTiles>");                        
        bw.newLine();
        bw.write("\t\t<verticalTiles>" + txtVerticalStem.getText() + "</verticalTiles>");                        
        bw.newLine();
        bw.write("\t\t<topTiles>" + txtTopTrunk.getText() + "</topTiles>");                        
        bw.newLine();
        bw.write("\t</stemTextures>");   
    }
    
    public void deletePreviousAndSaveTiles(File textureDir){
        File dirTrunk = new File(textureDir, "Trunk");
        File dirStem = new File(textureDir, "Stem");
        File dirLeaf = new File(textureDir, "Leaf");
        try {                        
            if(emptyDir(dirTrunk)){
                ArrayList<BufferedImage> tiles = trunkTextureCreator.getTiles();
                for(int i = 0; i < tiles.size(); i++){
                    File tile = new File(dirTrunk,"tile_" + i + ".png");
                    ImageIO.write(tiles.get(i), "png", tile);            
                }                
            }
            if(emptyDir(dirStem)){
                ArrayList<BufferedImage> tiles = stemTextureCreator.getTiles();
                for(int i = 0; i < tiles.size(); i++){
                    File tile = new File(dirStem,"tile_" + i + ".png");
                    ImageIO.write(tiles.get(i), "png", tile);            
                }                
            }
            if(emptyDir(dirLeaf)){
                ArrayList<BufferedImage> tiles = leafTextureCreator.getTiles();
                for(int i = 0; i < tiles.size(); i++){
                    File tile = new File(dirLeaf,"tile_" + i + ".png");
                    ImageIO.write(tiles.get(i), "png", tile);            
                }                
            }            
        } catch (Exception ex) {            
            JOptionPane.showMessageDialog(null, ex);
        }        
    }
    
    private void updateTrunkSeed(){
        try{
            Long seed = Long.parseLong(txtSeedTrunk.getText());
            if(seed != trunkTextureCreator.getSeed()){
                trunkTextureCreator.setSeed(seed);
                updateTrunkTexture();
            }
        }catch(Exception exc){}            
    }
    
    private void updateStemSeed(){
        try{
            Long seed = Long.parseLong(txtSeedStem.getText());
            if(seed != stemTextureCreator.getSeed()){
                stemTextureCreator.setSeed(seed);
                updateStemTexture();
            }
        }catch(Exception exc){}            
    }
    
    private void updateLeafSeed(){
        try{
            Long seed = Long.parseLong(txtSeedLeaf.getText());
            if(seed != leafTextureCreator.getSeed()){
                leafTextureCreator.setSeed(seed);
                updateLeafTexture();
            }
        }catch(Exception exc){}            
    }
    
    private boolean emptyDir(File dir){
        try{
            for(File f : dir.listFiles()){
                if(f.isDirectory()){
                    emptyDir(f);
                }else{
                    f.delete();
                }
            }
        }catch(Exception exc){}
        return dir.isDirectory() && dir.listFiles().length == 0;
    }
    
    public String getSeeds(){
        return txtSeedTrunk.getText() + "_" + txtSeedStem.getText() + "_" + txtSeedLeaf.getText();
    }
    
    private class Thumbnail extends JLabel{
        private BufferedImage image;
        public Thumbnail(File file){            
            ImageIcon icon = new ImageIcon(file.getAbsolutePath());
            Image img = icon.getImage();            
            image = toBufferedImage(img);
            icon.setImage(img.getScaledInstance(64, 64, Image.SCALE_FAST));            
            this.setIcon(icon);
        }
        
        public Thumbnail(Image image, int width, int height){                        
            if(image != null){
                this.image = toBufferedImage(image);
                ImageIcon icon = new ImageIcon(image);            
                icon.setImage(image.getScaledInstance(width, height, Image.SCALE_FAST));
                this.setIcon(icon);
            }
            revalidate();
        }
        
        public BufferedImage getOriginalImage(){
            return image;            
        }
        
        public void setIconImage(Image image, int width, int height){            
            this.image = toBufferedImage(image);
            ImageIcon icon = new ImageIcon(image);            
            icon.setImage(image.getScaledInstance(width, height, Image.SCALE_FAST));
            this.setIcon(icon);            
            revalidate();
        }                
        
        private  BufferedImage toBufferedImage(Image image) {
            if (image instanceof BufferedImage) {
                return (BufferedImage)image;
            }

            // This code ensures that all the pixels in the image are loaded
            image = new ImageIcon(image).getImage();

            // Determine if the image has transparent pixels; for this method's
            // implementation, see Determining If an Image Has Transparent Pixels
            boolean hasAlpha = hasAlpha(image);

            // Create a buffered image with a format that's compatible with the screen
            BufferedImage bimage = null;
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            try {
                // Determine the type of transparency of the new buffered image
                int transparency = Transparency.OPAQUE;
                if (hasAlpha) {
                    transparency = Transparency.BITMASK;
                }

                // Create the buffered image
                GraphicsDevice gs = ge.getDefaultScreenDevice();
                GraphicsConfiguration gc = gs.getDefaultConfiguration();
                bimage = gc.createCompatibleImage(
                    image.getWidth(null), image.getHeight(null), transparency);
            } catch (HeadlessException e) {
                // The system does not have a screen
            }

            if (bimage == null) {
                // Create a buffered image using the default color model
                int type = BufferedImage.TYPE_INT_RGB;
                if (hasAlpha) {
                    type = BufferedImage.TYPE_INT_ARGB;
                }
                bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
            }

            // Copy image to buffered image
            Graphics g = bimage.createGraphics();

            // Paint the image onto the buffered image
            g.drawImage(image, 0, 0, null);
            g.dispose();

            return bimage;
        }

        private boolean hasAlpha(Image image) {
            // If buffered image, the color model is readily available
            if (image instanceof BufferedImage) {
                BufferedImage bimage = (BufferedImage)image;
                return bimage.getColorModel().hasAlpha();
            }

            // Use a pixel grabber to retrieve the image's color model;
            // grabbing a single pixel is usually sufficient
             PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
            try {
                pg.grabPixels();
            } catch (InterruptedException e) {
            }

            // Get the image's color model
            ColorModel cm = pg.getColorModel();
            return cm.hasAlpha();
        }
    }
}
